<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>MutationObserver接口-基本用法</title>
  </head>
  <body>
    <div id="app">
      <button onclick="changeStyle()">修改Content样式</button>
      <div id="content"></div>
    </div>
  </body>
  <script>
    /* 1.定义：
     *   a.MutationObserver 接口，可以在 DOM 被修改时异步执行回调。使用 MutationObserver 可以观察整个【文档】、DOM 树的一部分，
     *     或【某个元素】。此外还可以观察【元素属性】、【子节点】、【文本】，或者前三者任意组合的变化。
     */

    /*2.基本用法
     *  1.observe()方法:新创建的 MutationObserver 实例不会关联 DOM 的任何部分。要把这个 observer 与 DOM 关联起来，需要使用 observe()方法。这个方法接
     *    收两个必需的参数：要观察其变化的 DOM 节点，以及一个 MutationObserverInit 对象。MutationObserverInit 对象用于控制观察哪些方面的变化，是一个键/
     *    值对形式配置选项的字典。
     *  2.回调与 MutationRecord：每个回调（函数）都会收到一个 MutationRecord 实例的数组。MutationRecord 实例包含的信息包括发生了什么变化，以及 DOM 的
     *    哪一部分受到了影响。因为回调执行之前可能同时发生多个满足观察条件的事件，所以每次执行回调都会传入一个包含按顺序入队的 MutationRecord 实例的数组。
     *  3.disconnect()方法：默认情况下，只要被观察的元素不被垃圾回收，MutationObserver 的回调就会响应 DOM 变化事件，从而被执行。要提前终止执行回调，可以
     *    调用 disconnect()方法。下面的例子演示了同步调用disconnect()之后，不仅会停止此后变化事件的回调，也会抛弃已经加入任务队列要异步执行的回调：
     *
     */
    let flag = true; //标识
    function changeStyle() {
      //获取DOM
      let contentDOM = document.getElementById("content");
      //设置样式
      if (flag) {
        let styleStr = "width:80px;height:60px;border:1px solid black";
        contentDOM.style = "width:240px;height:180px;border:1px solid black";
        flag = false;
      } else {
        contentDOM.style = 'display:none';
        flag = true;
      }
    }

    function checkBasicUsage() {
      //1.MutationObserver 的实例要通过调用 MutationObserver 构造函数并传入一个回调函数来创建
      let mutationObserver = new MutationObserver(() => {
        console.log("<body> attribute changed!");
      });
      //2.关联相应的DOM，并配置 MutationObserverInit实例对象
      mutationObserver.observe(document.body, { attributes: true });
      //3.修改相应的DOM的节点
      document.body.className = "foo";
      //4.打印修改的内容
      console.log("Change body attributes!");
    }
    // checkBasicUsage();
    //Change body attributes!
    //<body> attribute changed!（回调函数异步执行）

    function checkMutationRecord() {
      //1.创建MutationObserver实例
      let observer = new MutationObserver(
        (mutationRecordInstance, mutationObserverInstance) => {
          //mutationRecordInstance:返回一个数组，记录每一次监听变化的实例
          //mutationObserverInstance:返回当前观察变化的 MutationObserver 的实例
          console.log("mutationRecordInstance--", mutationRecordInstance);
          console.log("mutationObserverInstance--", mutationObserverInstance);
        }
      );
      //2.将监听关联到相对应的DOM上，并配置监听的数据字典
      // childList: true,观察目标子节点的变化，是否有添加或者删除
      // attributes: true,观察属性变动
      // characterData: true,观察文本节点的变动
      observer.observe(document.body, {
        attributes: true,
        childList: true,
        characterData: true,
      });
      //3.第一次的attribute涉及到添加了一个attribute，会触发childList监听
      document.body.id = "zw";
      document.body.id = "app";
      document.body.appendChild(document.createTextNode("HELLO WORLD"));
      console.log("change body!");
    }
    // checkMutationRecord();

    function checkDisconnect() {
      //1.创建MutationObserver实例
      let mutationObserverInstance = new MutationObserver(()=>{
        console.log('content attrubute change');
      });
      //2.将实例绑定到相应的DOM上
      let targetDOM = document.getElementById('content');
      mutationObserverInstance.observe(targetDOM,{"attributes":true});
      //3.调用disconnect(),直接结束监听，此时不会触发事件
      //mutationObserverInstance.disconnect();
      //要想让已经加入任务队列的回调执行，可以使用 setTimeout()让已经入列的回调执行完毕再调用disconnect()：
      setTimeout(()=>{
        mutationObserverInstance.disconnect();
        targetDOM.className = 'DISCONNECT';
      },5000)
      //结束
      console.log('dom changed!!');
    }
    checkDisconnect();
  </script>
</html>
